package com.zq.vaccinum.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zq.vaccinum.constant.Constants;
import com.zq.vaccinum.domain.LoginUser;
import com.zq.vaccinum.domain.entity.User;
import com.zq.vaccinum.domain.entity.UserInfo;
import com.zq.vaccinum.mapper.UserInfoMapper;
import com.zq.vaccinum.mapper.UserMapper;
import com.zq.vaccinum.service.IUserService;
import com.zq.vaccinum.service.ex.user.*;
import com.zq.vaccinum.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author zq
 * @since 2023-05-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    //定义json解析工具
    @Autowired
    private ObjectMapper objectMapper;


    /**
     * 用户登录业务 账号密码登录
     *
     * @param username
     * @param password
     * @return
     */
    public String login(String username, String password, String code, String uuid) {
        System.out.println("用户名:" + username);
        System.out.println("用户输入的验证码:" + code);
        // 校验验证码
        validateCaptcha(username, code, uuid);
        LoginUser loginUser = null;
        // 使用SpringSecurity进行用户认证

        // 认证主体(用户名)、凭证(密码)
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        // AuthenticationManager进行用户认证，该方法会去调用UserDetailsServiceImpl.loadUserByUsername方法
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        loginUser = (LoginUser) authenticate.getPrincipal();

//        // 查询用户是否存在
//        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
//        // 用户不存在
//        if (user == null) {
//            throw new UserNotFoundException();
//        }
//        // 密码匹配工具
//        PasswordEncoder encoder = new BCryptPasswordEncoder();
//        boolean matches = encoder.matches(password, user.getPassword());
//        // 密码不正确
//        if (matches == false) {
//            throw new PasswordNotMatchException();
//        }


        // 获取登录令牌token key
        String tokenKey = loginUser.getToken();
        // 用户存在且密码正确,存入token载体
        HashMap<String, Object> map = new HashMap<>();
        map.put(Constants.JWT_USERNAME, loginUser.getUsername());
//        map.put(Constants.JWT_USERID, loginUser.getUserId());
        map.put(Constants.LOGIN_USER_KEY, tokenKey);
        String token = JwtTokenUtil.createToken(map);

        // 登录令牌的Redis key
        String redisTokenKey = Constants.LOGIN_TOKENS + tokenKey;
        // 将redisTokenKey作为key，用户信息作为value存入redis
        redisTemplate.opsForValue().set(redisTokenKey, loginUser);
        return token;
    }

    /**
     * 手机号登录
     *
     * @param phone
     * @param password
     * @return
     */
    public String loginByPhone(String phone, String password, String code, String uuid) throws JsonProcessingException {
        validateCaptcha(phone, code, uuid);
        User user = new User();
        user.setPhone(phone);
        user.setPassword(password);
        User one = userMapper.selectOne(new QueryWrapper<User>(user));
        if (one != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put(Constants.JWT_USERNAME, one.getUsername());
            map.put(Constants.JWT_USERID, one.getId());
            return JwtTokenUtil.createToken(map);
        }
        return null;
    }


    public void validateCaptcha(String username, String code, String uuid) {
//        // 获取正确的验证码，存入session
//        String captcha = (String) session.getAttribute("captcha");
        if (code == null) {
            throw new CaptchaException("请输入验证码");
        }
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        System.out.println(verifyKey);
        // 从Redis拿到正确的验证码
        String captcha = (String) redisTemplate.opsForValue().get(verifyKey);
        // 验证码为空时,验证码过期
        if (captcha == null) {
            throw new CaptchaExpireException(Constants.ERROR,"验证码过期");
        }
        // 进行验证码判断,不区分大小写
        if (!code.equalsIgnoreCase(captcha)) {
            throw new CaptchaException(Constants.ERROR,"验证码错误");
        }
        // 校验验证码成功，从redis删除captcha
        redisTemplate.delete(verifyKey);
    }

    /**
     * 用户注册
     *
     * @param user
     */
    @Override
    public void register(User user) {
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("username", user.getUsername());
        User result = userMapper.selectOne(objectQueryWrapper);
        // 用户已存在
        if (result != null) {
            throw new UsernameDuplicatedException();
        }
        objectQueryWrapper.eq("phone", user.getPhone());
        result = userMapper.selectOne(objectQueryWrapper);
        // 用户手机号已存在
        if (result != null) {
            throw new PhoneDuplicatedException();
        }
        // 对密码进行加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        // 插入用户数据
        int insert = userMapper.insert(user);
        // 初始化用户详细信息,默认绿码
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(user.getId());
        if (insert != 1) {
            throw new InsertException();
        }
    }

    /**
     * 逻辑删除
     *
     * @param user
     */
    @Override
    public void softDelete(User user) {
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("username", user.getUsername())
                .eq("password", user.getPassword());
        // 验证账号密码是否正确
        User result = userMapper.selectOne(objectQueryWrapper);
        // 账号不存在
        if (result == null) {
            throw new UserNotFoundException();
        }
        user.setIs_deleted(1);
    }

    /**
     * 物理删除
     *
     * @param user
     */
    @Override
    public void delete(User user) {
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("username", user.getUsername())
                .eq("password", user.getPassword());
        // 验证账号密码是否正确
        User result = userMapper.selectOne(objectQueryWrapper);
        // 账号不存在
        if (result == null) {
            throw new UserNotFoundException();
        }
        int deleteUser = userMapper.delete(objectQueryWrapper);
        int deleteUserInfo = userInfoMapper.deleteById(user.getId());
        // 删除异常
        if (deleteUser == 1 && deleteUserInfo == 1) {
            throw new DeleteException();
        }
    }

    @Override
    public User getUserInfo(String username) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username",username));
        return user.setUserInfo(userInfoMapper.selectById(user.getId()));
    }

    /**
     * 查询用户所有信息，分页
     *
     * @return
     */
    @Override
    public HashMap findAllUser(Integer pageNum, Integer pageSize, String keyword) {

        // 通过page进行分页查询【当前页、每页显示的记录条数】
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>().like(keyword != null && !keyword.equals(""), "name", keyword);
        Page page = userMapper.selectPage(new Page<User>(pageNum, pageSize), queryWrapper);
        // 从page中获取list集合数据
        List<User> list = page.getRecords();
        //  保存到结果中
        HashMap result = new HashMap();
        result.put("list", list);
        result.put("total", page.getTotal());
        return result;
    }



    @Override
    public void logout() {
        // 获取SecurityContextHolder中的ID
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String tokenKey = loginUser.getToken();
        String redisTokenKey = Constants.LOGIN_TOKENS + tokenKey;
        // 删除redis中的值
        redisTemplate.delete(redisTokenKey);
    }


}
